﻿/*
 * NetModule.h
 */
#ifndef __GDK_NETMODULE_H__
#define __GDK_NETMODULE_H__

#include <gdk/core/Task.h>
#include <gdk/core/Thread.h>
#include <gdk/core/MessageDispenser.h>
#include <gdk/core/Callback.h>
#include <gdk/net/Socket.h>
#include <gdk/net/NetSystem.h>
#include <gdk/net/NetSession.h>
#include <gdk/net/NetAddress.h>
#include <gdk/net/NetMessage.h>
#include <gdk/net/NetEvent.h>


namespace gdk
{


	/////////////////////////////////////////////////////////////////////
	typedef CallbackHandler<bool, NetSession*> NetSessionCallback;


	/////////////////////////////////////////////////////////////////////
	class GDK_NET_EXPORT NetModule : public Task
	{
		DECLARE_CLASS_HANDLE(NetModule)

	private:
		Thread::Handle			_netThread;
		NetSystemPtr			_netSystem;
		MessageDispenser<void>	_messageDispenser;
		EventDispenser			_eventDispenser;
		NetSessionMap			_mapNetSession;

		Uuid					_acceptClientId;
		NetAddress				_acceptNetAddress;
		Uuid					_acceptPeerSocketId;

		uint32_t				_timeout; // 处理指令超时时间

	protected:
		NetModule(NetSystem *netSystem);

	public:
		virtual bool init(void);
		virtual void exit(void);
		virtual void onTick(uint32_t timeSinceLastTick);

	public:
		__INLINE__ MessageDispenser<void>& getMessageDispenser(void) { return _messageDispenser; }
		__INLINE__ EventDispenser& getEventDispenser(void) { return _eventDispenser; }

	public:
		bool pushMessage(const Message::Handle &msg);
		void setMessageSemaphore(Semaphore *semaphore);

		void setTimeout(uint32_t timeout) { _timeout = timeout; }

	private:
		bool addNetSession(NetSession *netSession);
		void removeNetSession(NetSession *netSession);
	public:
		NetSession* getNetSession(const Uuid &clientId) const;
		ssize_t getNetSessionCount(void) const { return _mapNetSession.size(); }
		void foreach(const NetSessionCallback &callback);
		void foreach(bool(*func)(NetSession *))
		{
			return foreach(NetSessionCallback(func));
		}
		template<typename TyClass> void foreach(TyClass *obj, bool(TyClass::*func)(NetSession *))
		{
			return foreach(NetSessionCallback(obj, func));
		}
		template<typename TyClass> void foreach(TyClass &obj, bool(TyClass::*func)(NetSession *))
		{
			return foreach(NetSessionCallback(obj, func));
		}
		template<typename TyClass> void foreach(SharedPtr<TyClass> const &obj, bool(TyClass::*func)(NetSession *))
		{
			return foreach(NetSessionCallback(obj, func));
		}
		template<typename TyClass> void foreach(gdk::Unknown::Handle_T<TyClass> const &obj, bool(TyClass::*func)(NetSession *))
		{
			return foreach(NetSessionCallback(obj, func));
		}
		//-----------------------------------------------------

	public:
		bool accept(NetSession *netSession);
		bool connect(NetSession *netSession, const NetAddress &addr, const Uuid &socketId = UUID_NULL);
		void close(NetSession *netSession);
		bool send(NetSession *netSession, Message *msg);

	private:
		void onNetStart(NetStart *msg);
		void onNetShutdown(NetShutdown *msg);
		void onNetAccept(NetAccept *msg);
		void onNetConnectOk(NetConnectOk *msg);
		void onNetConnectFail(NetConnectFail *msg);
		void onNetBlocking(NetBlocking *msg);
		void onNetRestored(NetRestored *msg);
		void onNetClosed(NetClosed *msg);
		void onNetError(NetError *msg);
		void onNetAbort(NetAbort *msg);
		void onNetReceive(NetReceive *msg);
	};
	typedef NetModule::Handle NetModulePtr;


	//----------------------------------------------------------------------------
	GDK_NET_EXPORT NetModulePtr createNetModule(const String &protocol = __TEXT__("xtcp"), uint16_t port = 0);


} //namespace gdk


#endif //__GDK_NETMODULE_H__
